package appapi.utils;

import appapi.Global.BusinessException;
import appapi.entity.basic.UserInfo;
import com.alipay.api.internal.util.StringUtils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import io.jsonwebtoken.*;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Date;
import java.util.Map;

import static java.security.KeyRep.Type.SECRET;

/**
 * 请求对象
 *
 * @author luocheng
 * @version 1.0
 * @date 2023/06/05 15:07
 */
public class JwtUtil {
    //    token 时效 12小时
    public static final long EXPIRE = 1000 * 60 * 60 * 12;
//    public static final long EXPIRE = 1000 * 60 * 60 * 24 * 30 * 6;
    //    签名哈希的密钥，对于不同的加密算法来说含义不同

    public static final String APP_SECRET = "hss200923usersToken";

    /**
     * 根据用户id和用户名生成token
     *
     * @param userid   用户id
     * @param username 用户名称
     * @param mobile   联系电话
     * @return JWT规则生成的token
     */
    public static String getJwtToken(Long userid, String mobile, String username) {
        String JwtToken = Jwts.builder()
                .setHeaderParam("typ", "JWT")
                .setHeaderParam("alg", "HS256")
                .setSubject("users")
                .setIssuedAt(new Date())//token 保留时间
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRE))//token失效时间
                .claim("userid", userid)
                .claim("mobile", mobile)
                .claim("username", username)
                //HS256算法实际上就是MD5加盐值，此时APP_SECRET就代表盐值
                .signWith(SignatureAlgorithm.HS256, APP_SECRET)
                .compact();
        return JwtToken;
    }


    /**
     * 判断token是否存在与有效
     *
     * @param jwtToken token字符串
     * @return 如果token 有效返回true，否则返回false
     */
    public static boolean checkToken(String jwtToken) {
        if (StringUtils.isEmpty(jwtToken)) return false;
        try {
            //验证有效期
            JwtUtil.isJwtExpired(jwtToken);
        } catch (Exception ex) {
            throw new BusinessException(-1, "token过期");
        }
        try {
            Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
        } catch (Exception e) {
            return false;
        }
        return true;
    }


    /**
     * 根据token 获取用户username
     *
     * @param token 请求对象
     * @return 解析token后获得的用户id
     */
    public static String getUserName(String token) {
        DecodedJWT decodeToken = JWT.decode(token);
        return decodeToken.getClaim("userName").asString();

    }

    /**
     * 获取用户手机号
     *
     * @param token
     * @return
     * @throws Exception
     */
    public static Long getUserId(String token) throws Exception {

        Map<String, Claim> claims = verifyToken(token);
        Claim user_id_claim = claims.get("user_id");
        if (null == user_id_claim || StringUtils.isEmpty(user_id_claim.asString())) {
            return 0L;
        }
        return Long.valueOf(user_id_claim.asString());
    }

    public static Map<String, Claim> verifyToken(String token) throws Exception {
        DecodedJWT jwt = null;
        JWTVerifier verifier = JWT.require(Algorithm.HMAC256(APP_SECRET)).build();
        jwt = verifier.verify(token);

        return jwt.getClaims();

    }

    /**
     * @desc 判断token是否过期
     */
    public static void isJwtExpired(String token) throws TokenExpiredException {
        try {
            token = safeToken(token);
            DecodedJWT decodeToken = JWT.decode(token);
            Boolean bRet = decodeToken.getExpiresAt().before(new Date());
            if (bRet) {
                throw new TokenExpiredException("有效期过期");
            }
        } catch (TokenExpiredException e) {

        }
    }

    public static UserInfo getUserInfo(String token) {
        token = safeToken(token);
        DecodedJWT decodeToken = JWT.decode(token);
        UserInfo user = new UserInfo();
        user.setUserid(decodeToken.getClaim("userid").asLong());
        user.setMobile(decodeToken.getClaim("mobile").asString());
        user.setUsername(decodeToken.getClaim("username").asString());
        return user;
    }

    public static String safeToken(String token) {
        return token.replace("Bearer ", "").replace("Bearer%20", "");
    }

    /**
     * 根据token 获取用户信息数组
     *
     * @param request Http 请求对象
     * @return 解析token后获得的用户0为名称, 1为电话
     */
    public static String[] getUserInfoByJwtToken(HttpServletRequest request) {
        String jwtToken = request.getHeader("token");
        if (StringUtils.isEmpty(jwtToken)) throw new BusinessException(500, "token为空!");
        Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
        Claims claims = claimsJws.getBody();
        String[] userInfo = new String[2];
        userInfo[0] = (String) claims.get("username");
        userInfo[1] = (String) claims.get("mobile");
        return userInfo;
    }

    public static Long getUserIdByJwtToken(String token) {
        //String jwtToken = request.getHeader("token");
        if (StringUtils.isEmpty(token)) return 0L;
        Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(token);
        Claims claims = claimsJws.getBody();
        return Long.parseLong(claims.get("userid").toString());
    }

}